//simple stop condition
//$Id: stop_condition.h 441 2010-04-09 17:27:20Z Oleg.Bulychov $
#pragma once

namespace stop_condition
{

template<class E, class S>
struct abstract_stop_condition:
    public ref_object
{
    virtual int get_Max_Step() = 0;
    virtual bool stop(E& env, typename S::TCostType& cost, int nStep) = 0;
};

template<class E, class S>
struct max_step:
    public factory_object< max_step<E, S>, abstract_stop_condition<E, S> >
{
protected:
    int         value_;
public:
    explicit max_step()
    {
        accept(meta::set_default_values());
    }

    static char const* get_Name() { return "max_step"; }

    template<class V>
    void accept(V& v)
    {
        v(VAR_(value),   100);
    }

    virtual int get_Max_Step()
    {
        return value_;
    }

    virtual bool stop(E& env, typename S::TCostType& cost, int nStep)
    {
        return nStep > value_;
    }
};

template<class E, class S>
struct cost_limit:
    public factory_object< cost_limit<E, S>, abstract_stop_condition<E, S> >
{
protected:
    typename S::TCostType   value_;
public:
    explicit cost_limit()
    {
        accept(meta::set_default_values());
    }

    static char const* get_Name() { return "cost_limit"; }

    template<class V>
    void accept(V& v)
    {
        v(VAR_(value), typename S::TCostType());
    }

    virtual int get_Max_Step()
    {
        return INT_MAX;
    }

    virtual bool stop(E& env, typename S::TCostType& cost, int nStep)
    {//:stop if cost is better or equal to value_
        return !(typename inverted_direction<typename S::TDirection>::result()(cost, value_));
    }
};


template<class X>
struct validator: public meta::abstract_validator
{
    template<class U>
    void set_Default(std::vector< ref_ptr<U> >& v) const
    {
        v.clear();
        X* px = new X;
        ref_ptr<U> pt;
        pt.attach(px);
        v.push_back(pt);
    }
};

}

//EOF!
